package com.chisheng.caa.service;

import com.chisheng.caa.exception.ValueNotFoundException;
import com.chisheng.caa.pojo.Bean;
import com.chisheng.caa.pojo.DuplicateStrategy;
import org.springframework.lang.Nullable;

import java.util.Collection;
import java.util.Map;

/**
 * 增删改查操作接口。访问键不存在时抛出异常。
 *
 * @param <T> 操作类型
 */
public interface CRUD<T extends Bean> {

    /**
     * 添加元素。元素重复时由重复策略处理。
     *
     * @param accessKey 访问键
     * @param t         元素实例
     * @throws NullPointerException 访问键不存在时抛出
     */
    default void add(String accessKey, T t) {
        throw new UnsupportedOperationException();
    }

    /**
     * 返回元素重复处理策略。默认不允许元素重复。
     *
     * @return 元素重复处理策略
     */
    default DuplicateStrategy getDuplicateStrategy(@Nullable String accessKey) {
        return DuplicateStrategy.NOT_ALLOWED;
    }

    /**
     * 移除元素。元素不存在时忽略。
     *
     * @param accessKey 访问键
     * @param id        元素 id
     * @throws NullPointerException 访问键不存在时抛出
     */
    default void remove(String accessKey, String id) {
        throw new UnsupportedOperationException();
    }

    /**
     * 修改元素。元素不存在抛出异常。
     *
     * @param accessKey 访问键
     * @param t         元素实例
     * @throws NullPointerException   访问键不存在时抛出
     * @throws ValueNotFoundException 元素不存在时抛出
     */
    default void modify(String accessKey, T t) {
        throw new UnsupportedOperationException();
    }

    /**
     * 获取元素。元素不存在返回 null。
     *
     * @param accessKey 访问键
     * @param id        元素 id
     * @return 元素实例
     * @throws NullPointerException 访问键不存在时抛出
     */
    default T getOne(String accessKey, String id) {
        throw new UnsupportedOperationException();
    }

    /**
     * 获取元素集合。没有元素时返回空集合。
     *
     * @param accessKey 访问键
     * @return 元素集合
     * @throws NullPointerException 访问键不存在时抛出
     */
    default Collection<T> getCollection(String accessKey) {
        throw new UnsupportedOperationException();
    }

    /**
     * 状态
     */
    interface State<T extends Bean> {

        /**
         * 返回状态数据
         *
         * @return 状态数据
         */
        Map<String, T> getData();

        /**
         * 设定状态数据
         *
         * @param data 状态数据
         */
        default void setData(Map<String, ? extends T> data) {
            throw new UnsupportedOperationException();
        }

    }

}
